package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.pojo.AccountBalanceSheetDO;
import com.laicunba.pojo.AccountDO;
import com.laicunba.pojo.FinancingTargetBidDO;
import com.laicunba.pojo.WithdrawDO;
import com.laicunba.service.AccountBalanceSheetService;
import com.laicunba.service.AccountService;
import com.laicunba.service.WithdrawService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.MD5Util;
import com.laicunba.util.StringUtil;

@Service
public class AccountBalanceSheetImpl extends BaseServiceImpl implements AccountBalanceSheetService {

	public static final MathContext MC = new MathContext(10, RoundingMode.HALF_DOWN);
	@Autowired
	private AccountService accountService;
	@Autowired
	private WithdrawService withdrawService;

	private String genSign(AccountDO accountDO, AccountBalanceSheetDO sdo) {
		return MD5Util.md5Hex(String.format("%s|%s|%s|%s|%s|%s", sdo.getAccountId(), sdo.getBalance(), sdo.getCertificateId(), sdo.getDr(), sdo.getCr(), sdo.getRowNum()));
	}

	@Transactional
	@Override
	public boolean accountingBankPay(FinancingTargetBidDO bidDO) {

		// 记账增加银行存款
		BigDecimal incomeMoney = bidDO.getCashCouponAmount() == null || bidDO.getCashCouponAmount().compareTo(BigDecimal.ZERO) == 0 ? bidDO.getBuyAmount()
				: bidDO.getBuyAmount().subtract(bidDO.getCashCouponAmount(), MC);
		String rid = addBankCash(bidDO.getCertificateId(), incomeMoney, null, "银行卡购买");

		// 记账增加负债
		if ("SCB".equalsIgnoreCase(bidDO.getType())) {
			rid = addHDebt(bidDO.getCertificateId(), bidDO.getBuyAmount(), rid, "银行卡购买");
		} else {
			rid = addDDebt(bidDO.getCertificateId(), bidDO.getBuyAmount(), rid, "银行卡购买");
		}

		// 现金券，记入应付费用
		if (bidDO.getCashCouponAmount() != null && bidDO.getCashCouponAmount().compareTo(BigDecimal.ZERO) > 0) {
			addCostNeedPay(bidDO.getCertificateId(), bidDO.getCashCouponAmount(), rid, "银行卡购买使用现金券");
		}
		return true;
	}

	/**
	 * 增加费用
	 * 
	 * @param certificateId
	 * @param amt
	 * @param rid
	 * @param remark
	 * @return
	 */
	private String addCostNeedPay(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "COST_NEEDPAY");
		AssertUtil.assertTrue(accountDO != null, "COST_NEEDPAY_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
		accountBalanceSheetDO.setDr(amt);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");

		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	private String addCostPayed(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "COST_PAYED");
		AssertUtil.assertTrue(accountDO != null, "COST_PAYED_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
		accountBalanceSheetDO.setDr(amt);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");

		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;

	}

	/**
	 * 记账增加定期负债
	 * 
	 * @param bidDO
	 * @param rid
	 * @param remark
	 * @return
	 */
	private String addDDebt(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "DEBT_D");
		AssertUtil.assertTrue(accountDO != null, "DEBT_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
		accountBalanceSheetDO.setDr(amt);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");

		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;

	}

	/**
	 * 记账增加活期负债
	 * 
	 * @param bidDO
	 * @param rid
	 * @param remark
	 * @return
	 */
	private String addHDebt(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "DEBT_H");
		AssertUtil.assertTrue(accountDO != null, "DEBT_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
		accountBalanceSheetDO.setDr(amt);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;

	}

	/**
	 * 记账增加银行存款
	 * 
	 * @param bidDO
	 * @return
	 */
	private String addBankCash(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "BANK_CASH");
		AssertUtil.assertTrue(accountDO != null, "BANK_CASH_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
		accountBalanceSheetDO.setDr(amt);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	private String subtractBankCash(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "BANK_CASH");
		AssertUtil.assertTrue(accountDO != null, "BANK_CASH_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().subtract(amt, MC));
		accountBalanceSheetDO.setDr(BigDecimal.ZERO);
		accountBalanceSheetDO.setCr(amt);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
		AssertUtil.assertTrue(accountService.subtractBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	@Transactional
	@Override
	public boolean accountingH2D(FinancingTargetBidDO bidDO) {
		BigDecimal money = bidDO.getCashCouponAmount() == null || bidDO.getCashCouponAmount().compareTo(BigDecimal.ZERO) == 0 ? bidDO.getBuyAmount()
				: bidDO.getBuyAmount().subtract(bidDO.getCashCouponAmount(), MC);
		// 活期负债减少
		String rid = subtractHDebt(bidDO.getCertificateId(), money, null, "活转定");
		// 增加定期负债
		rid = addDDebt(bidDO.getCertificateId(), bidDO.getBuyAmount(), rid, "活转定");
		// 现金券，记入已付费用
		if (bidDO.getCashCouponAmount() != null && bidDO.getCashCouponAmount().compareTo(BigDecimal.ZERO) > 0) {
			addCostNeedPay(bidDO.getCertificateId(), bidDO.getCashCouponAmount(), rid, "活转定使用现金券");
		}
		// 如果是非复活转定，则需要将当时产生的利息，计入应付费用
		if (bidDO.getCertificateId().startsWith("D2F-")) {
			/*
			String withdrawId = bidDO.getCertificateId().substring(4);
			BigDecimal profit = withdrawService.countProfit(withdrawId);
			if (profit != null && profit.compareTo(BigDecimal.ZERO) > 0) {
				addCostNeedPay(bidDO.getCertificateId(), profit, rid, "非复活产生的利息");
			}*/
		}
		return true;
	}

	/**
	 * 减少活期负债
	 * 
	 * @param certificateId
	 * @param amt
	 * @param rid
	 * @param remark
	 * @return
	 */
	private String subtractHDebt(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "DEBT_H");
		AssertUtil.assertTrue(accountDO != null, "DEBT_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().subtract(amt, MC));
		accountBalanceSheetDO.setDr(BigDecimal.ZERO);
		accountBalanceSheetDO.setCr(amt);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
		AssertUtil.assertTrue(accountService.subtractBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	@Transactional
	@Override
	public boolean accountingWithdrawApply(WithdrawDO withdrawDO) {
		
		if("SCB".equalsIgnoreCase(withdrawDO.getType())){
			BigDecimal  profit=	withdrawService.countProfit(withdrawDO.getId());
			BigDecimal principal = profit!=null&&profit.compareTo(BigDecimal.ZERO)>0?withdrawDO.getWithdrawPrincipal().subtract(profit):withdrawDO.getWithdrawPrincipal();
			String certificateId = "wid:"+withdrawDO.getId();
			// 减少活期负债
			String rid = subtractHDebt(certificateId, withdrawDO.getWithdrawPrincipal(), null, "非复活提现申请");
			// 减少银存 
			subtractBankCash(certificateId, principal, rid, "非复活提现申请");
			//加回款本金
			addPaymentPrincipal(certificateId, principal, rid, "非复活提现申请");
			//加已付费用
			if(profit!=null && profit.compareTo(BigDecimal.ZERO)>0){
				addCostPayed(certificateId, profit, rid, "非复活提现申请");	
			}			
		}else if("ca".equalsIgnoreCase(withdrawDO.getType())){
			BigDecimal  profit=	withdrawService.countLastCurrentWithdrawProfit(withdrawDO.getUserId());
			BigDecimal principal = profit!=null&&profit.compareTo(BigDecimal.ZERO)>0?withdrawDO.getWithdrawPrincipal().subtract(profit):withdrawDO.getWithdrawPrincipal();
			String certificateId =  "wid:"+withdrawDO.getId();
			// 减少活期负债
			String rid = subtractHDebt(certificateId, withdrawDO.getWithdrawPrincipal(), null, "复活提现申请");
			// 减少银存 
			subtractBankCash(certificateId, principal, rid, "复活提现申请");
			//加回款本金
			addPaymentPrincipal(certificateId, principal, rid, "复活提现申请");
			//加已付费用
			if(profit!=null && profit.compareTo(BigDecimal.ZERO)>0){
				addCostPayed(certificateId, profit, rid, "复活提现申请");	
			}
		}
		
		
		/*
		// 减少活期负债
		String certificateId = "wid:" + withdrawDO.getId();
		String rid = subtractHDebt(certificateId, withdrawDO.getWithdrawPrincipal(), null, "提现申请");
		// 减少银行存款
		subtractBankCash(certificateId, withdrawDO.getWithdrawPrincipal(), rid, "提现申请");
		// 减少应付费用
		if (withdrawDO.getWithdrawProfit() != null && withdrawDO.getWithdrawProfit().compareTo(BigDecimal.ZERO) > 0) {
			subtractCostNeedPay(certificateId, withdrawDO.getWithdrawProfit(), rid, "提现申请");
			addCostPayed(certificateId, withdrawDO.getWithdrawPrincipal(), rid, "提现申请");
		}
		*/
		return true;
	}

	private String addPaymentPrincipal(String certificateId, BigDecimal principal, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "PAYMENT_PRINCIPAL");
		AssertUtil.assertTrue(accountDO != null, "PAYMENT_PRINCIPAL_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().add(principal, MC));
		accountBalanceSheetDO.setDr(principal);
		accountBalanceSheetDO.setCr(BigDecimal.ZERO);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
		AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), principal, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	private String subtractCostNeedPay(String certificateId, BigDecimal amt, String rid, String remark) {
		rid = StringUtil.isEmpty(rid) ? StringUtil.genGUID() : rid;
		AccountDO accountDO = accountService.get(AccountDO.class, "COST_NEEDPAY");
		AssertUtil.assertTrue(accountDO != null, "COST_NEEDPAY_ACCOUNT_NOT_EXIST");

		AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
		accountBalanceSheetDO.setAccountId(accountDO.getId());
		accountBalanceSheetDO.setCertificateId(certificateId);
		accountBalanceSheetDO.setBalance(accountDO.getBalance().subtract(amt, MC));
		accountBalanceSheetDO.setDr(BigDecimal.ZERO);
		accountBalanceSheetDO.setCr(amt);
		accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(certificateId));
		accountBalanceSheetDO.setStatus(0);
		accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
		accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
		accountBalanceSheetDO.setRid(rid);
		accountBalanceSheetDO.setRemark(remark);
		AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");

		AssertUtil.assertTrue(accountService.subtractBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");
		return rid;
	}

	@Transactional
	@Override
	public boolean accounting(String rid, Map<String, BigDecimal> map, String remak) {

		AssertUtil.assertTrue(map != null && !map.isEmpty(), "IMPROVE_DATA_IS_EMPTY");
		AssertUtil.assertTrue(StringUtil.isNotEmpty(rid), "RID_IS_EMPTY");
		AssertUtil.assertTrue((Integer) queryDao.selectOne("ACCOUNT_BALANCE_SHEET.countRID", rid) == 0, "RID_EXIST");

		for (String subjectId : map.keySet()) {
			BigDecimal amt = map.get(subjectId);

			AccountDO accountDO = accountService.get(AccountDO.class, subjectId);
			AssertUtil.assertNotNull(accountDO, "SUBJECT_NOT_EXIST");
			AssertUtil.assertNotNull(amt, "AMT_NOT_EXIST");
			AssertUtil.assertTrue(BigDecimal.ZERO.compareTo(amt) != 0, "AMT_CANT_BE_ZERO");

			if (amt.compareTo(BigDecimal.ZERO) > 0) {
				// 加

				AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
				accountBalanceSheetDO.setAccountId(accountDO.getId());
				accountBalanceSheetDO.setCertificateId(rid);
				accountBalanceSheetDO.setBalance(accountDO.getBalance().add(amt, MC));
				accountBalanceSheetDO.setDr(amt);
				accountBalanceSheetDO.setCr(BigDecimal.ZERO);
				accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(rid));
				accountBalanceSheetDO.setStatus(0);
				accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
				accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
				accountBalanceSheetDO.setRid(rid);
				accountBalanceSheetDO.setRemark(remak);
				AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
				AssertUtil.assertTrue(accountService.addBalance(accountDO.getId(), amt, accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");

			} else {
				// 减

				AccountBalanceSheetDO accountBalanceSheetDO = new AccountBalanceSheetDO();
				accountBalanceSheetDO.setAccountId(accountDO.getId());
				accountBalanceSheetDO.setCertificateId(rid);
				accountBalanceSheetDO.setBalance(accountDO.getBalance().subtract(amt, MC));
				accountBalanceSheetDO.setDr(BigDecimal.ZERO);
				accountBalanceSheetDO.setCr(amt.abs());
				accountBalanceSheetDO.setId(accountDO.getId() + "." + MD5Util.md5Hex(rid));
				accountBalanceSheetDO.setStatus(0);
				accountBalanceSheetDO.setRowNum(accountDO.getRowNum() + 1);
				accountBalanceSheetDO.setSign(genSign(accountDO, accountBalanceSheetDO));
				accountBalanceSheetDO.setRid(rid);
				accountBalanceSheetDO.setRemark(remak);
				AssertUtil.assertTrue(create(accountBalanceSheetDO), "CREATE_ACCOUNT_BALANCE_SHEET_FAIL");
				AssertUtil.assertTrue(accountService.subtractBalance(accountDO.getId(), amt.abs(), accountDO.getBalance(), accountDO.getRowNum()), "UPDATE_ACCOUNT_FAIL");

			}

		}
		AssertUtil.assertTrue(accountService.totalBalance().compareTo(BigDecimal.ZERO) == 0, "BALANCE_NOT_ZERO");

		return true;

	}

	@Transactional
	@Override
	public boolean accountingImprove(Map<String, BigDecimal> map, String remark) {
		AssertUtil.assertTrue(map != null && !map.isEmpty(), "IMPROVE_DATA_IS_EMPTY");

		String rid = "improve_" + StringUtil.genGUID();
		AssertUtil.assertTrue(accounting(rid, map, remark), "ACCOUNTING_FAIL");
		return true;
	}

}
